#include "queue.h"
#include "game.h"
#include "actor.h"
#include "buffer.h"

extern GameInfo Game;
extern Buffer Buff;

Event::Event(Object* target_,int delay_,EventType type_,string msg_) : target(target_),delay(delay_),type(type_),attr(NO_ATTR),
		msg(msg_),value(0),time_created(Game.Turn()),dead(false){
		//move along
}
Event::Event(Object* target_,int delay_,EventType type_,AttrType attr_,string msg_,int value_) : target(target_),delay(delay_),
		type(type_),attr(attr_),msg(msg_),value(value_),time_created(Game.Turn()),dead(false){
		//nothing to see here
}
bool Event::IsLessThan(Event* ptr){
	if(TimeToExecute() < ptr->TimeToExecute()){
		return true;
	}
	else{
		return false;
	}
}
void Event::Kill(Object* target_,EventType type_){
	if(target==target_ && (type==type_ || type_==ANY_EVENT)){
		dead = true;
	}
}
void Event::Execute(){
	if(!dead){
		switch(type){
			case MOVE:
				{
					Actor* temp = dynamic_cast<Actor*>(target);
					temp->Input();
					break;
				}
			case REMOVE_ATTR:
				{
					Actor* temp = dynamic_cast<Actor*>(target);
					temp->LoseAttr(attr,value);
					if(msg!=""){
						Buff.Rec(msg);
					}
					break;
				}
			default:
				break;
		}
	}
}
void Queue::Add(Event* ptr){
	node* temp = new node;
	temp->dataptr = ptr;
	if(first==NULL){
		first=temp;
		last=temp;
		temp->next=NULL;
		temp->prev=NULL;
	}
	else{
		current=last;
		bool done=false;
		while(current->prev && !done){
			if(ptr->IsLessThan(current->dataptr)){
				current=current->prev;
			}
			else{
				done=true;
			}
		}
		if(done){
			if(current->next==NULL){
				current->next=temp;
				temp->prev=current;
				temp->next=NULL;
				last=temp;
			}
			else{
				temp->prev=current;
				temp->next=current->next;
				current->next->prev=temp;
				current->next=temp;
			}
		}
		else{
			if(ptr->IsLessThan(current->dataptr)){
				temp->prev=NULL;
				temp->next=current;
				current->prev=temp;
				first=temp;
			}
			else{
				if(current->next==NULL){
					current->next=temp;
					temp->prev=current;
					temp->next=NULL;
					last=temp;
				}
				else{
					temp->prev=current;
					temp->next=current->next;
					current->next->prev=temp;
					current->next=temp;
				}
			}
		}
	}
}
void Queue::AddToFront(Event* ptr){
	node* temp = new node;
	temp->dataptr=ptr;
	if(first==NULL){
		first=temp;
		last=temp;
		temp->next=NULL;
		temp->prev=NULL;
	}
	else{
		temp->next=first;
		temp->prev=NULL;
		first->prev=temp;
		first=temp;
	}
}
void Queue::Pop(){
	Game.Advance(first->dataptr->TimeToExecute());
	first->dataptr->Execute();
	node* temp = first->next;
	delete first->dataptr;
	delete first;
	first=temp;
	first->prev=NULL;
}
void Queue::KillEvents(Object* target,EventType type){
	for(current=first;current!=NULL;current=current->next){
		current->dataptr->Kill(target,type);
	}
}

